function Transition(e, opacity, minimum, maximum)
{
	this.element = e;
	this.opacity = opacity || 0;
	this.minimum = minimum || 0;
	this.maximum = maximum || 100;
	
	minimum = minimum || 0;
	maximum = maximum || 100;
	
	setOpacity(this, opacity || 0);
	
	var timer = null;
	var animation = null;
	
	function setFilter(object, filterId, value)
	{
		var f = object.element.style.filter || "";
		var filter = null;
		var index = 0;
		
		while (index >= 0)
		{
			var startBracket = f.indexOf("(", index);
			var endBracket = f.indexOf(")", index);
			
			if (startBracket >= 0 && endBracket >= 0)
			{
				var id = f.substr(index, startBracket - index).replace(/^\s+|\s+$/g, "");
	
				if (id != filterId)
				{
					filter = ((filter != null) ? filter + ", " : "") + id + "(" + f.substr(startBracket + 1, endBracket - startBracket - 1) + ")";
				}
			}
			else
				break;
			
			index = f.indexOf(",", endBracket);
			if (index >= 0)
				index++;
		}
		
		filter = ((filter != null) ? filter + ", " : "") + filterId + "(" + value + ");";
		object.element.style.filter = filter;
	}
	
	function setOpacity(object, opacity)
	{
		object.opacity = opacity;
		object.element.style.opacity = opacity / 100;
		setFilter(object, "alpha", "opacity=" + Math.floor(opacity));
		//object.element.style.filter = "alpha(opacity=" + opacity + ");";
	}
	
	function setDisplay(object, display)
	{
		if (display == null)
			return;
		
		object.element.style.display = display;
	}
	
	function setPosition(object, x, y)
	{
		object.element.style.left = x + "px";
		object.element.style.top = y + "px";
	}
	
	function startTransition(object, type, duration, args, callback)
	{
		if (type != "stop")
		{
			if (animation) //&& animation != type
				stopAnimation(object, args, callback);
		
			if (!animation || true)
			{
				animation = type;

				switch (type)
				{
					case "in":
						setDisplay(object, args.display);
						break;
					case "out":
						break;
					case "move":
						break;
				}
				
				transition(object, type, duration, args, callback);
			}
		}

		switch (type)
		{
			case "in":
				break;
			case "out":
				break;
			case "move":
				break;
			case "stop":
				animation = null;
				if (timer)
				{
					clearTimeout(timer);
					timer = null;
				}
				if (callback)
					callback(object);
				
				break;
		}
	}
	
	function stopAnimation(object, args, callback)
	{
		startTransition(object, "stop", 0, args, callback);
	}
	
	function playAnimation(object, type, duration, args, callback, frames)
	{
		timer = setTimeout(function ()
									 {
										 transition(object, type, duration, args, callback);
									 }
									 , duration / frames);
	}
	
	function transition(object, type, duration, args, callback)
	{
		var fps = 60;
		var seconds = duration / 1000;
		var frames = seconds * fps;
		
		switch (type)
		{
			case "in":
				if (object.opacity < maximum)
				{
					setOpacity(object, Math.min(maximum, object.opacity + (maximum - minimum) / frames));
					playAnimation(object, type, duration, args, callback, frames);
				}
				else
				{
					setOpacity(object, maximum);
					stopAnimation(object, args, callback);
				}
				
				break;
			case "out":
				if (object.opacity > minimum)
				{
					setOpacity(object, Math.max(minimum, object.opacity - (maximum - minimum) / frames));
					playAnimation(object, type, duration, args, callback, frames);
				}
				else
				{
					setOpacity(object, minimum);
					setDisplay(object, args.display);
					stopAnimation(object, args, callback);
				}
				
				break;
			case "move":
				if (object.x != args.endX || object.y != args.endY)
				{
					object.x += (args.endX - args.startX) / frames;
					object.y += (args.endY - args.startY) / frames;
					
					if (Math.abs(object.x - args.endX) < 1 && Math.abs(object.y - args.endY) < 1)
					{
						object.x = args.endX;
						object.y = args.endY;
					}
					
					playAnimation(object, type, duration, args, callback, frames);
					setPosition(object, object.x, object.y); 
				}
				else
				{
					setDisplay(object, args.display);
					stopAnimation(object, args, callback);
				}
			
				break;
		}
	}
	
	this.fadeIn = function(duration, display, callback)
		{
			startTransition(this, "in", duration || 500, { display:display }, callback);
		}
	
	this.fadeOut = function(duration, display, callback)
		{
			startTransition(this, "out", duration || 500, { display:display }, callback);
		}
		
	this.move = function(duration, start, end, callback)
		{
			this.x = start.x;
			this.y = start.y;
			setPosition(this, this.x, this.y); 
					
			startTransition(this, "move", duration || 500, { startX:start.x, startY:start.y, endX:end.x, endY:end.y }, callback);
		}
		
	this.abort = function()
	{
		stopAnimation(this, null, null);
	}
}